﻿using System;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Text;
using System.Runtime.InteropServices;
using Microsoft.Win32;

namespace WindowsAeroTuner
{
    public partial class FrmMain : Form
    {
        public struct DwmColorParams
        {
            public UInt32 ColorizationColor;
            public UInt32 ColorizationAfterglow;
            public UInt32 ColorizationColorBalance;
            public UInt32 ColorizationAfterglowBalance;
            public UInt32 ColorizationBlurBalance;
            public UInt32 ColorizationGlassReflectionIntensity;
            public UInt32 ColorizationOpaqueBlend;
        };
        Color Rgb(int color)
        {
            int alpha = 0xFF & color;
            int r = 0xFF00 & color;
            int g = 0xFF0000 & color;
            g >>= 8;
            int b = 0xFF0000 & color;
            b >>= 16;
            return Color.FromArgb(alpha,r, g, b);
        }
// ReSharper disable MemberCanBeMadeStatic.Local
        uint ParseRgb(Color color)
// ReSharper restore MemberCanBeMadeStatic.Local
        {
            return (uint)(((uint)color.R << 16) | (ushort)(((ushort)color.G << 8) | color.B));
        }
        //
        private DwmApi.MARGINS _mGlassMargins;
        private enum RenderMode
        { None, EntireWindow, TopWindow, Region };
        private RenderMode _mRenderMode;
        private Region _mBlurRegion;
        private readonly ColorDialog colorDialog1;
        private DwmColorParams Colors;
        private const uint Rgbuint = 4278190080;
        //
        [DllImport("dwmapi.dll", EntryPoint = "#127")]
        static extern int DwmpGetColorizationParameters(out DwmColorParams dcpParams);
        [DllImport("dwmapi.dll", EntryPoint = "#131")]
        static extern int DwmpSetColorizationParameters(ref DwmColorParams dcpParams, bool alwaysTrue);
        
        public FrmMain()
        {
            _mRenderMode = RenderMode.None;
            colorDialog1 = new ColorDialog();
            InitializeComponent();
            ResetDwmBlurBehind();
            _mGlassMargins = new DwmApi.MARGINS(0, 50, 0, 0);
            _mRenderMode = RenderMode.TopWindow;

            if (DwmApi.DwmIsCompositionEnabled()) 
                DwmApi.DwmExtendFrameIntoClientArea(this.Handle, _mGlassMargins);

            // reset window border style in case DwmEnableBlurBehindWindow was set
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
            this.Colors = new DwmColorParams();
            this.Invalidate();
        }
        // This is a trick to get Windows to treat glass as part of the caption
        // area I learned from Daniel Moth.
        protected override void WndProc(ref Message msg)
        {
            base.WndProc(ref msg); // let the normal winproc process it

            const int WM_DWMCOMPOSITIONCHANGED = 0x031E;
            const int WM_NCHITTEST = 0x84;
            const int HTCLIENT = 0x01;

            switch (msg.Msg)
            {
                case WM_NCHITTEST:
                    if (HTCLIENT == msg.Result.ToInt32())
                    {
                        // it's inside the client area

                        // Parse the WM_NCHITTEST message parameters
                        // get the mouse pointer coordinates (in screen coordinates)
                        Point p = new Point();
                        p.X = (msg.LParam.ToInt32() & 0xFFFF);// low order word
                        p.Y = (msg.LParam.ToInt32() >> 16); // hi order word

                        // convert screen coordinates to client area coordinates
                        p = PointToClient(p);

                        // if it's on glass, then convert it from an HTCLIENT
                        // message to an HTCAPTION message and let Windows handle it from then on
                        if (PointIsOnGlass(p))
                            msg.Result = new IntPtr(2);
                    }
                    break;

                case WM_DWMCOMPOSITIONCHANGED:
                    if (!DwmApi.DwmIsCompositionEnabled())
                    {
                        _mRenderMode = RenderMode.None;
                        _mGlassMargins = null;
                        if (_mBlurRegion != null)
                        {
                            _mBlurRegion.Dispose();
                            _mBlurRegion = null;
                        }
                    }
                    break;
            }
        }

        private bool PointIsOnGlass(Point p)
        {
            // test for region or entire client area
            // or if upper window glass and inside it.
            // not perfect, but you get the idea
            return _mGlassMargins != null &&
                (_mGlassMargins.cyTopHeight <= 0 ||
                 _mGlassMargins.cyTopHeight > p.Y);
        }

        private void OnPaint(object sender, PaintEventArgs e)
        {
            if (DwmApi.DwmIsCompositionEnabled())
            {
                switch (_mRenderMode)
                {
                    case RenderMode.EntireWindow:
                        e.Graphics.FillRectangle(Brushes.Black, this.ClientRectangle);
                        break;

                    case RenderMode.TopWindow:
                        e.Graphics.FillRectangle(Brushes.Black, Rectangle.FromLTRB(0, 0, this.ClientRectangle.Width, _mGlassMargins.cyTopHeight));
                        break;

                    case RenderMode.Region:
                        if (_mBlurRegion != null) e.Graphics.FillRegion(Brushes.Black, _mBlurRegion);
                        break;
                }
            }

            // You can experiment with text colors & opacities (255 = opaque, 0-0-0 = black)
            using (SolidBrush textBrush = new SolidBrush(Color.FromArgb(255, 0, 0, 0)))
            {
                e.Graphics.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit;
                e.Graphics.DrawString("This is writing on glass", this.Font, textBrush, 10, 10);
            }
        }    
        private void ResetDwmBlurBehind()
        {
            if (DwmApi.DwmIsCompositionEnabled())
            {
                DwmApi.DWM_BLURBEHIND bbhOff = new DwmApi.DWM_BLURBEHIND();
                bbhOff.dwFlags = DwmApi.DWM_BLURBEHIND.DWM_BB_ENABLE | DwmApi.DWM_BLURBEHIND.DWM_BB_BLURREGION;
                bbhOff.fEnable = false;
                bbhOff.hRegionBlur = IntPtr.Zero;
                DwmApi.DwmEnableBlurBehindWindow(this.Handle, bbhOff);
            }
        }

        
        private void FrmMainLoad(object sender, EventArgs e)
        {
            DwmColorParams Colors = new DwmColorParams();
            DwmpGetColorizationParameters(out Colors);
            
            trackBar1.Value = (int)Colors.ColorizationAfterglowBalance;
            trackBar2.Value = (int)Colors.ColorizationColorBalance;
            trackBar3.Value = (int)Colors.ColorizationBlurBalance;
            trackBar4.Value = (int)Colors.ColorizationGlassReflectionIntensity;
            pictureBox9.BackColor = Color.FromArgb((int)Colors.ColorizationColor);
            pictureBox10.BackColor = Color.FromArgb((int)Colors.ColorizationAfterglow);
            chkAero.Checked = (int)Colors.ColorizationOpaqueBlend == 0;
        }

        private void CommBtnClick(object sender, EventArgs e)
        {
            RegistryKey regKey = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\DWM\\", true);
            if (regKey == null)
            {
                MessageBox.Show(@"Error!", @"Error",
                  MessageBoxButtons.OK, MessageBoxIcon.Error);
                return; 
            }
            regKey.SetValue("ColorizationColor", (int)Colors.ColorizationColor, RegistryValueKind.DWord);
            regKey.SetValue("ColorizationAfterglow", (int)Colors.ColorizationAfterglow, RegistryValueKind.DWord);
            regKey.SetValue("ColorizationColorBalance", (int)Colors.ColorizationColorBalance, RegistryValueKind.DWord);
            regKey.SetValue("ColorizationAfterglowBalance", (int)Colors.ColorizationAfterglowBalance, RegistryValueKind.DWord);
            regKey.SetValue("ColorizationBlurBalance", (int)Colors.ColorizationBlurBalance, RegistryValueKind.DWord);
            regKey.SetValue("ColorizationOpaqueBlend", (int)Colors.ColorizationOpaqueBlend, RegistryValueKind.DWord);
            regKey.SetValue("ColorizationGlassReflectionIntensity", (int)Colors.ColorizationGlassReflectionIntensity, RegistryValueKind.DWord);
            regKey.Close();
            //MessageBox.Show("OK","Infomaction",
            //    MessageBoxButtons.OK,MessageBoxIcon.Information);
            commBtnOK.Enabled = false;
        }
        private int SetColorizationParameters(int aeroColor, int afterglow, int afterglowBalance, int colorBalance,
            int blurBalance, int aeroStripes, bool opaqueBlend)
        {
            //DwmpGetColorizationParameters(out Colors);
            commBtnOK.Enabled = true;
            Colors.ColorizationColor = (uint)aeroColor;
            Colors.ColorizationAfterglow = (uint)afterglow;
            Colors.ColorizationAfterglowBalance = (uint)afterglowBalance;
            Colors.ColorizationColorBalance = (uint)colorBalance;
            Colors.ColorizationBlurBalance = (uint)blurBalance;
            Colors.ColorizationGlassReflectionIntensity = (uint)aeroStripes;
            Colors.ColorizationOpaqueBlend = (uint)(opaqueBlend ? 0 : 1);
            return DwmpSetColorizationParameters(ref Colors, true);
        }
        private void ChangeStyle(object sender, EventArgs e)
        {
            SetColorizationParameters((int)(ParseRgb(pictureBox9.BackColor) + Rgbuint),
                (int)(ParseRgb(pictureBox10.BackColor) + Rgbuint),trackBar1.Value,
                trackBar2.Value, trackBar3.Value, trackBar4.Value, chkAero.Checked);
        }

        private void ColorBoxClick(object sender, EventArgs e)
        {
            PictureBox pbx = (PictureBox)sender;
            Colors.ColorizationColor = Rgbuint + ParseRgb(pbx.BackColor);
            pictureBox9.BackColor = pbx.BackColor;
            ChangeStyle(sender, e);
        }

        private void CommBtnCloseClick(object sender, EventArgs e)
        {
            this.Close();
        }

        private void ClolorBalanceClick(object sender, EventArgs e)
        {
            PictureBox pbx = (PictureBox)sender;           
            DialogResult result = colorDialog1.ShowDialog(this);
            if (result == System.Windows.Forms.DialogResult.OK)
            {
                pbx.BackColor = colorDialog1.Color;
                ChangeStyle(sender,e);
            }
        }

        private void LnkPageLinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("http://www.tooyoos.com");
        }
    }
}
